#ifndef C_COMPILER_FIRST_H
#define C_COMPILER_FIRST_H
#include <Global.h>
#include <iterator>

void getFirst(const string& ch) {
    vector<string> ch_production = production_map[ch]; // 该符号的产生式
    unordered_set<string> set = FirstSet[ch];
    // 当ch为终结符
    if (VtSet.count(ch)) {
        set.insert(ch);
        FirstSet[ch] = set;
        return;
    }
    // ch为非终结符
    for (const string& str : ch_production) {
        istringstream iss(str);
        vector<string> temp2((istream_iterator<string>(iss)), istream_iterator<string>());
        int i = 0;
        while (i < temp2.size()) {
            string tn = temp2[i];
            // 递归
            getFirst(tn);
            unordered_set<string> tvSet = FirstSet[tn];
            // 将其first集加入左部
            for (const string& tmp : tvSet) {
                if (tmp != "$") {
                    set.insert(tmp);
                }
            }
            // 若包含空串处理下一个符号
            if (tvSet.count("$")) {
                i++;
            } else {
                break;
            }
        }
        if (i == temp2.size()) { // 所有的符号的first集合中均有$符号
            set.insert("$");
        }
    }
    FirstSet[ch] = set;
}
void First() {
    // 遍历求每一个非终结符vn的first集
    for (const string& vn : VnSet) {
        getFirst(vn);
    }
}
void getFirstOfBeta(const string& s) {
    unordered_set<string> set = FirstSetBeta[s];
    istringstream iss(s);
    vector<string> temp3((istream_iterator<string>(iss)), istream_iterator<string>());
    int i = 0;
    while (i < temp3.size()) {
        string tn = temp3[i];
        if (!FirstSet.count(tn)) {
            getFirst(tn);
        }
        unordered_set<string> tvSet = FirstSet[tn];
        // 将其非空first集加入左部
        for (const string &tmp: tvSet) {
            if (tmp != "$") {
                set.insert(tmp);
            }
        }
        // 若包含空串处理下一个符号
        if (tvSet.count("$")) {
            i++;
        } else {
            break;
        }
        // 到了尾部，即所有符号的first集都包含空串，把空串加入
        if (i == temp3.size()) {
            set.insert("$");
        }
    }
    FirstSetBeta[s] = set;

}
#endif //C_COMPILER_FIRST_H
